BI.Engine = (function(executionContextCallback){
	
	if (!executionContextCallback){
		throw new Exception("Please define executionContextCallback");
	}
	
	var canvas = new Element('canvas', {width : 10000, height : 10000});
	var context = canvas.getContext('2d'); 
	var requestAnimationFrame =  (function() {
		return window.requestAnimationFrame 
		|| window.webkitRequestAnimationFrame
		|| window.mozRequestAnimationFrame 
		|| window.oRequestAnimationFrame
		|| window.msRequestAnimationFrame
		|| function(/* function */callback, /* DOMElement */element) {
			window.setTimeout(callback, 1000 / 60);
		};
	})();
	
	var gameContext =  {
		
		/**
		 * Allows to preload specified images 
		 * @param config
		 */
		preloadImages: function(config){
			var numberOfImages = 0;
			
			for (var imageIndex in config.images){
				numberOfImages++;
			};
			
			var currentElement = 0;
			var results = {};
			
			for (var imageIndex in config.images){
				results[imageIndex] = new BI.core.ImageResource();
				results[imageIndex].image.onload = function(){
					currentElement++; 
					config.onProgress({current: currentElement, total: numberOfImages});
					
					if (currentElement == numberOfImages){
						for (var resultIndex in results){
							context.clearRect(0, 0, 10000, 10000);
							context.drawImage(results[resultIndex].image, 0, 0);
							results[resultIndex].data = context.getImageData(0, 0 , results[resultIndex].image.width, results[resultIndex].image.height);
						}
						
						delete canvas;
						delete context;
						config.onSuccess(results);
					} else {
						
					}
				};
				results[imageIndex].image.src = config.images[imageIndex].src; 
			};
		},
		
		/**
		 * Starts execution of animation by executing i
		 * @param loopCallback
		 */
		runInAnimLoop:function(loopCallback){
			(function animloop() {
				loopCallback();
				requestAnimationFrame(animloop, null);
			})();
		}
	};
	
	executionContextCallback(gameContext);

});